package com.base.monitor.framework.handler;

import com.base.monitor.framework.result.Result;
import com.base.monitor.model.enums.code.BaseCode;
import com.base.monitor.model.enums.code.impl.common.ParamCode;
import com.base.monitor.model.enums.code.impl.common.ServerCode;
import com.base.monitor.model.enums.code.impl.common.UploadCode;
import com.base.monitor.framework.exception.CustomerException;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 统一异常处理类
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    // 使用EXCEPTIONS存放异常类型和错误代码的映射
    protected static ImmutableMap<Class<? extends Throwable>, BaseCode> EXCEPTIONS;

    //使用builder来构建一个异常类型和错误代码的异常
    protected static ImmutableMap.Builder<Class<? extends Throwable>, BaseCode> builder = ImmutableMap.builder();

    // 构建EXCEPTIONS的信息
    static {
        builder.put(HttpMessageNotReadableException.class, ParamCode.PARAM_TYPE_BIND_ERROR);
        builder.put(org.springframework.web.multipart.MaxUploadSizeExceededException.class, UploadCode.FILE_TOO_BIG);
    }

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(CustomerException.class)
    public Result dealWithCustomerException(CustomerException e) {
        log.error("发生异常：{}", e.getMessage(), e);
        return Result.failure(e.getResultCode(), e.getMessage());
    }

    /**
     * 处理校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result dealWithValidException(MethodArgumentNotValidException e) {
        log.error("内容校验失败：{}", e.getMessage(), e);
        StringBuilder sb = new StringBuilder();
        for (ObjectError error : e.getBindingResult().getAllErrors()) {
            sb.append(error.getDefaultMessage()).append(" ");
        }
        return Result.failure(ParamCode.PARAM_VALIDATE_FAILURE, sb.toString());
    }

    /**
     * 处理其他异常
     */
    @ExceptionHandler(Exception.class)
    public Result dealWithOtherException(Exception e) {
        log.error("发生异常：{}", e.getMessage(), e);
        if (EXCEPTIONS == null) {
            EXCEPTIONS = builder.build();
        }
        final BaseCode result = EXCEPTIONS.get(e.getClass());
        if (result != null) {
            return Result.failure(result);
        } else {
            return Result.failure(ServerCode.SERVER_OCCURS_ERROR);
        }
    }
}

